#!/usr/bin/env bash
#
# list_sys_info.sh
#
# 功能：
#  1. 系统概览：获取内核信息、系统架构、发行版信息以及系统运行时间。
#  2. 硬件详情：获取 CPU、内存、磁盘信息。
#  3. GPU 信息：显示 NVIDIA GPU 的型号、显存和利用率（如果存在）。
#  4. 网络状态：获取默认网络信息（默认接口、网关、DNS、公共 IP）以及各接口的主要信息
#     （MAC 地址、IPv4/IPv6 地址、网速、工作模式）。
#     网络速率将格式化为“10 Mbps”、“100 Mbps”、“1000 Mbps”等。
#  5. 电池信息：检测并显示电池容量和状态（如果检测到电池）。
#  6. 运行时信息：获取系统负载和当前时间。

set -euo pipefail
shopt -s nullglob

# -------------------------------
# 常量定义
# -------------------------------
readonly SCRIPT_NAME="SysInfoPlus"
readonly TIMESTAMP_FORMAT="%Y-%m-%d %H:%M:%S"

# -------------------------------
# 辅助函数
# -------------------------------
print_section() {
    local -r header="$1"
    printf "\n\033[1;36m=== %s ===\033[0m\n" "$header"
}

print_info() {
    local -r label="$1"
    local -r value="$2"
    if [[ -n "$value" && "$value" != "N/A" ]]; then
        printf "\033[1;34m%-30s\033[0m : %s\n" "$label" "$value"
    fi
}

command_exists() {
    command -v "$1" >/dev/null 2>&1
}

safe_command() {
    if ! output=$("$@" 2>/dev/null); then
        echo "[ERROR] Command failed: $*" >&2
        return 1
    fi
    echo "$output"
}

# -------------------------------
# 系统概览
# -------------------------------
get_kernel_info() {
    print_info "Kernel Name" "$(uname -s)"
    print_info "Kernel Release" "$(uname -r)"
    print_info "Kernel Version" "$(uname -v)"
}

get_system_arch() {
    print_info "Architecture" "$(uname -m)"
    print_info "Processor Type" "$(uname -p)"
    print_info "Hardware Platform" "$(uname -i)"
}

get_distro_info() {
    local distro="Unknown"
    if command_exists lsb_release; then
        distro=$(lsb_release -ds 2>/dev/null || echo "Unknown")
    elif [[ -f /etc/os-release ]]; then
        distro=$(grep -oP 'PRETTY_NAME="\K[^"]+' /etc/os-release || echo "Unknown")
    elif [[ -f /etc/redhat-release ]]; then
        distro=$(cat /etc/redhat-release || echo "Unknown")
    fi
    print_info "Distribution" "$distro"
}

get_uptime_info() {
    local uptime_str="N/A"
    if command_exists uptime; then
        uptime_str=$(uptime -p | sed 's/^up //')
    elif [[ -f /proc/uptime ]]; then
        uptime_str=$(awk '{printf "%dd %dh %dm", int($1/86400), int($1%86400/3600), int($1%3600/60)}' /proc/uptime)
    fi
    print_info "Uptime" "$uptime_str"
}

# -------------------------------
# 硬件详情
# -------------------------------
get_cpu_info() {
    local model="N/A"
    local cores="N/A"
    local mhz="N/A"
    if command_exists lscpu; then
        model=$(lscpu | awk -F: '/Model name/ {print $2}' | xargs)
        cores=$(lscpu | awk -F: '/^CPU\(s\)/ {print $2}' | xargs | awk '{print $1}')
        mhz=$(lscpu | awk -F: '/CPU MHz/ {print $2}' | xargs)
    else
        model=$(awk -F: '/model name/ {print $2; exit}' /proc/cpuinfo | xargs)
        cores=$(awk '/^processor/ {count++} END {print count}' /proc/cpuinfo)
    fi
    print_info "CPU Model" "$model"
    print_info "CPU Cores" "$cores"
    [[ "$mhz" != "N/A" ]] && print_info "CPU MHz" "$mhz"
}

get_memory_info() {
    local total used free_mem
    total=$(free -b | awk '/^Mem:/ {print $2}')
    used=$(free -b | awk '/^Mem:/ {print $3}')
    free_mem=$(free -b | awk '/^Mem:/ {print $4}')
    print_info "Memory Total" "$(numfmt --to=iec "$total")"
    print_info "Memory Used" "$(numfmt --to=iec "$used")"
    print_info "Memory Free" "$(numfmt --to=iec "$free_mem")"
}

get_disk_info() {
    local size used avail pct
    size=$(df -h --total | awk '/total/ {print $2}')
    used=$(df -h --total | awk '/total/ {print $3}')
    avail=$(df -h --total | awk '/total/ {print $4}')
    pct=$(df -h --total | awk '/total/ {print $5}')
    print_info "Disk Size" "${size:-N/A}"
    print_info "Disk Used" "${used:-N/A}"
    print_info "Disk Available" "${avail:-N/A}"
    print_info "Disk Usage" "${pct:-N/A}"
}

# -------------------------------
# GPU 信息
# -------------------------------
get_gpu_info() {
    if command_exists nvidia-smi; then
        print_section "GPU Information"
        # 查询每块 GPU 的基本信息（索引、名称、总显存、已用显存、利用率）
        local gpu_info
        gpu_info=$(nvidia-smi --query-gpu=index,name,memory.total,memory.used,utilization.gpu --format=csv,noheader,nounits)
        while IFS=, read -r index name mem_total mem_used util; do
            index=$(echo "$index" | xargs)
            name=$(echo "$name" | xargs)
            mem_total=$(echo "$mem_total" | xargs)
            mem_used=$(echo "$mem_used" | xargs)
            util=$(echo "$util" | xargs)
            print_info "GPU $index Name" "$name"
            print_info "GPU $index Total Memory" "${mem_total} MiB"
            print_info "GPU $index Used Memory" "${mem_used} MiB"
            print_info "GPU $index Utilization" "${util}%"
        done <<< "$gpu_info"
    else
        print_section "GPU Information"
        print_info "GPU" "No NVIDIA GPU detected or nvidia-smi not installed"
    fi
}

# -------------------------------
# 网络相关函数
# -------------------------------
# 获取网络速率：读取 /sys/class/net/<iface>/speed 或 ethtool 输出，若为纯数字则附加单位 Mbps
get_network_speed() {
    local iface="$1"
    local speed="N/A"
    if [[ -f "/sys/class/net/$iface/speed" ]]; then
        speed=$(cat "/sys/class/net/$iface/speed" 2>/dev/null)
    fi
    if [[ -z "$speed" || "$speed" == "Unknown" || "$speed" == "-1" ]]; then
        if command_exists ethtool; then
            speed=$(ethtool "$iface" 2>/dev/null | awk -F': ' '/Speed:/ {print $2}' | tr -d ' ')
        fi
    fi
    if [[ "$speed" =~ ^[0-9]+$ ]]; then
        echo "${speed} Mbps"
    else
        echo "${speed:-N/A}"
    fi
}

# 获取接口工作模式：
# 对于无线接口，调用 iwconfig 获取 "Mode:" 字段；否则检查是否含有 PROMISC 标志
get_interface_mode() {
    local iface="$1"
    local mode=""
    if command_exists iwconfig; then
        mode=$(iwconfig "$iface" 2>/dev/null | grep "Mode:" | sed 's/.*Mode:\([^ ]*\).*/\1/')
    fi
    if [[ -n "$mode" ]]; then
        echo "$mode"
    else
        if ip link show "$iface" | grep -q "PROMISC"; then
            echo "Promiscuous"
        else
            echo "Normal"
        fi
    fi
}

# 获取公网 IP，优先使用 ifconfig.me，其次使用 ipinfo.io/ip
get_public_ip() {
    local ip
    ip=$(curl -s ifconfig.me 2>/dev/null)
    if [[ -z "$ip" ]]; then
        ip=$(curl -s ipinfo.io/ip 2>/dev/null)
    fi
    echo "${ip:-N/A}"
}

# 网络状态：显示默认网络信息及各接口主要信息（MAC、IPv4、IPv6、网速、工作模式）
get_network_info() {
    local default_iface default_gateway public_ip dns
    default_iface=$(ip route | awk '/default/ {print $5; exit}')
    default_gateway=$(ip route | awk '/default/ {print $3; exit}')
    public_ip=$(get_public_ip)
    dns=$(grep "^nameserver" /etc/resolv.conf | awk '{print $2}' | paste -sd ", ")

    print_info "Default Network Interface" "$default_iface"
    print_info "Default Gateway" "${default_gateway:-N/A}"
    print_info "DNS Servers" "${dns:-N/A}"
    print_info "Public IP" "${public_ip}"

    print_section "Network Interfaces"
    for iface in $(ls /sys/class/net/); do
        printf "\n\033[1;33m[ Interface: %s ]\033[0m\n" "$iface"
        local mac ipv4 ipv6 speed mode
        mac=$(cat /sys/class/net/"$iface"/address 2>/dev/null || echo "N/A")
        ipv4=$(ip -o -f inet addr show "$iface" | awk '{print $4}' | paste -sd ", " -)
        [[ -z "$ipv4" ]] && ipv4="N/A"
        ipv6=$(ip -o -f inet6 addr show "$iface" | awk '{print $4}' | paste -sd ", " -)
        [[ -z "$ipv6" ]] && ipv6="N/A"
        speed=$(get_network_speed "$iface")
        mode=$(get_interface_mode "$iface")
        print_info "MAC Address" "$mac"
        print_info "IPv4 Address" "$ipv4"
        print_info "IPv6 Address" "$ipv6"
        print_info "Network Speed" "$speed"
        print_info "Mode" "$mode"
    done
}

# -------------------------------
# 电池信息
# -------------------------------
get_battery_info() {
    if [[ -d /sys/class/power_supply/BAT0 ]]; then
        local capacity status
        capacity=$(cat /sys/class/power_supply/BAT0/capacity 2>/dev/null || echo "N/A")
        status=$(cat /sys/class/power_supply/BAT0/status 2>/dev/null || echo "N/A")
        print_section "Battery Info"
        print_info "Battery Capacity" "${capacity}%"
        print_info "Battery Status" "$status"
    else
        print_section "Battery Info"
        print_info "Battery" "No Battery Detected"
    fi
}

# -------------------------------
# 运行时信息
# -------------------------------
get_load_average() {
    local load_avg
    load_avg=$(awk '{printf "%s, %s, %s", $1, $2, $3}' /proc/loadavg)
    print_info "Load Average (1m, 5m, 15m)" "$load_avg"
}

get_current_time() {
    print_info "Current Time" "$(date "+${TIMESTAMP_FORMAT}")"
}

# -------------------------------
# 主函数
# -------------------------------
main() {
    echo -e "\n\033[1;35m${SCRIPT_NAME}\033[0m"

    print_section "System Overview"
    get_kernel_info
    get_system_arch
    get_distro_info
    get_uptime_info

    print_section "Hardware Details"
    get_cpu_info
    get_memory_info
    get_disk_info

    get_gpu_info

    print_section "Network Status"
    get_network_info

    get_battery_info

    print_section "Runtime Info"
    get_load_average
    get_current_time
}

# 脚本入口
main

